/*
 * @Author: your name
 * @Date: 2021-06-26 14:54:43
 * @LastEditTime: 2021-06-27 19:47:49
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \ttstar\assets\scripts\frameworks\UIPanel.ts
 */

import { GComponent, GObject } from "fairygui-cc";
import { EventDef } from "../common/EventDef";
import { EventSystem } from "../../frameworks/system/EventSystem";
import { MediatorBase } from "./MediatorBase";
import { Res } from "../../frameworks/res/Res";
import { ResCacheUI } from "../../frameworks/res/ResCacheUI"
import ResLoadQueue from "../../frameworks/res/ResLoadQueue";
import { UIItem } from "./UIItem";

export class UIMediator extends MediatorBase {

    protected resPath!: string;
    protected objName!: string;
    protected resDeps!: Array<string>;
    private _injects!: Array<any>;
    private _clickObjs!: Array<GObject> | null;
    private _items!: Array<UIItem> | null;

    protected _asset!: ResCacheUI | null;


    protected get pkg(): ResCacheUI | null {
        return this._asset;
    }

    public get view(): GComponent | null {
        return this._object;
    }

    /**
     * 显示对象
     * @param enable 
     */
    public set visible(enable: boolean) {
        if (this.view) {
            if (this.view.visible != enable)
                this.view.visible = enable;
        }
    }

    /**
     * 显示对象
     * @param enable 
     */
    public get visible(): boolean {
        if (this.view)
            return this.view.visible;
        return false;
    }

    /**
     * 加载准备
     * @param queue 
     */
    protected loadPrepare(queue: ResLoadQueue) {
        if (this.resDeps) {
            let resDeps = this.resDeps;
            for (let i = 0; i < resDeps.length; ++i) {
                queue.addPackage(resDeps[i]);
            }
        }
        super.loadPrepare(queue);
    }

    /**
     * 加载主资源
     */
    protected async loadMain(): Promise<any> {
        let asset = await Res.loadUIPackageAsync(this.resPath, true);
        if (!asset) return null;
        this._asset = asset;
        let obj = asset.spawn(this.objName);
        obj['name'] = this.objName;
        EventSystem.dispatch(EventDef.WINDOW_OPEN, this.objName);
        // console.log("[Open Window]: " + this.objName);
        return obj;
    }

    /**
     * 回收
     */
    protected clear() {
        super.clear();

        if (this._items) {
            for (let i = 0; i < this._items.length; ++i) {
                this._items[i].destroy();
            }
            this._items = null;
        }

        if (this._clickObjs) {
            for (let i = 0; i < this._clickObjs.length; ++i) {
                this._clickObjs[i].clearClick();
            }
            this._clickObjs = null;
        }

        if (this._object) {
            Res.recycle(this._object);
            this._object = null;
        }

        // if (this._asset) {
        //     UIPackage.removePackage(this._asset.path);
        //     this._asset = null;
        // }
    }

    /**
     * 通过路径获取子节点
     * @param path 
     * @returns 
     */
    public getChild(path: string): GObject | null {
        if (!this.view) return null;

        let obj;
        try {
            let gcom: any = this.view;
            let arr = path.split("/");
            let cnt = arr.length;
            for (let i = 0; i < cnt; ++i) {
                obj = gcom.getChild(arr[i]);
                if (!obj)
                    break;
                if (i != cnt - 1) {
                    if (!(obj instanceof GComponent)) {
                        obj = null;
                        break;
                    }
                    else
                        gcom = obj;
                }
            }
        }
        catch {
            return null;
        }
        return obj;
    }

    /**
     * 注入数据
     */
    protected inject() {
        super.inject();
        if (this._injects) {
            let that: any = this;
            for (let key in this._injects) {
                let inject = this._injects[key];
                let path = inject[1];
                let target = this.getChild(path);
                if (target) {
                    that[key] = target;
                }
                else {
                    console.warn("[%s]绑定控件失败：%s", this.resPath + "/" + this.objName, inject[1]);
                }
            }
        }
    }


    /**
     * 监听UI点击
     * @param callbcak 
     */
    protected listenClick(obj: GObject, callbcak: Function) {
        if (!obj) {
            console.error(`${this.objName} 监听的UI控件不存在`);
            return;
        }
        obj.clearClick();
        obj.onClick(callbcak, this);
        if (!this._clickObjs)
            this._clickObjs = [];
        this._clickObjs.push(obj);
    }

    /**
     * 绑定子项
     * @param target 
     * @param classT 
     * @param data 
     * @param args 
     */
    protected bindItem<T extends UIItem>(target: GObject, classT: { new(): T }, data: any, args?: any): T {
        var obj: any = target as any;
        var com: UIItem = obj["_itemHandler"];
        if (!com) {
            com = new classT();
            obj["_itemHandler"] = com;
            if (!this._items)
                this._items = [];
            this._items.push(com);
        }
        com.attach(target, data, args);
        return com as T;
    }
}